﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Mirkuz.PowerManagement;
using Microsoft.WindowsMobile.Samples.Location;
using System.Threading;

namespace Mirkuz.LocationServices
{
    public class GPSIDLocationProvider : LocationProviderBase, IDisposable
    {
        Thread _gpsthread;
        IntPtr _gpspwrreq;
        bool _end_thread;             
        Gps _gps;
        GpsPosition _currentpos;

        public GPSIDLocationProvider(int polltime)
        {
            _gpsthread = new Thread(new ThreadStart(GPS_Thread));
            _gpsthread.Name = "GPSIDLocationProvider_thread";
        }

        public override void Start()
        {
            _end_thread = false;
            base.Start();
            _gpsthread.Start();
        }

        public override void Stop()
        {
            base.Stop();
            _end_thread = true;
        }
       
        private void GPS_Thread()
        {
            int iretry = 0;
            DateTime lastfixtime=DateTime.Now;
            try
            {
                while (!_end_thread)
                {
                    _currentpos = null;

                    _gpspwrreq = PowerManager.SetRequirement("GPD0:", CEDEVICE_POWER_STATE.D0);

                    Thread.Sleep(1000);
                    _gps = new Gps();
                    _gps.Open();

                retry:
                    {
                        for (int i = 0; i < 5 && !_end_thread; i++)
                            Thread.Sleep(1000);
                        if (_end_thread)
                            break;

                        try
                        {
                            GpsPosition p = _gps.GetPosition();
                            int s = ((_pollingtime + 20) < 60) ? 60 : (_pollingtime + 20);

                            if (p != null
                                && p.SeaLevelAltitudeValid
                                && p.TimeValid
                                && p.LatitudeValid
                                && p.LongitudeValid
                                && p.Time != null
                                )
                            {
                                if (Math.Abs((int)lastfixtime.Subtract(p.Time).TotalSeconds) > 1)
                                    _currentpos = p;

                                lastfixtime = p.Time;
                            }
                        }
                        catch { _currentpos = null; }

                        if (!_end_thread)
                        {
                            if (_currentpos != null)
                                OnNewLocationAvailable(Location.FromGPSPosition(_currentpos));
                            else
                            {
                                iretry++;
                                if (iretry >= 10)
                                {
                                    iretry = 0;
                                    OnDifficultReception();
                                }
                                goto retry;
                            }
                        }
                    }

                    _gps.Close();
                    _gps = null;

                    PowerManager.ReleaseRequirement(_gpspwrreq);

                    for (int i = 5; (i < _pollingtime) && !_end_thread; i++)
                        Thread.Sleep(1000);
                }
            }
            catch (Exception e)
            {
                OnError(e);
            }
        }


        #region IDisposable Members

        public override void Dispose()
        {
            _end_thread = true;
            try { _gpsthread.Abort(); }
            catch { }

            if (_gps != null)
            {
                try
                {
                    _gps.Close();
                }
                catch { }
                try
                {
                    PowerManager.ReleaseRequirement(_gpspwrreq);
                }
                catch { }
            }

        }

        #endregion
    }
}
